package com.fjh.shop.user.service.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjh.shop.common.exceptions.BusinessException;
import com.fjh.shop.common.exceptions.enums.Resp;
import com.fjh.shop.user.model.dto.MemberLoginDTO;
import com.fjh.shop.user.model.dto.MemberRegisterDTO;
import com.fjh.shop.user.model.dto.MemberUpdatePasswordDTO;
import com.fjh.shop.user.model.entity.Member;
import com.fjh.shop.user.model.vo.MemberLoginVO;
import com.fjh.shop.user.service.handlers.BaseContextHandler;
import com.fjh.shop.user.service.mapper.MemberMapper;
import com.fjh.shop.user.service.service.MemberService;
import com.fjh.shop.user.service.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wuyunbin
 * @since 2025-07-15
 */
@Slf4j
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {
    @Resource
    private JwtUtil jwtUtil;

    @Resource
    private WxMaService wxMaService;

    @Resource
    private BCryptPasswordEncoder passwordEncoder;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Resource
    private HttpServletRequest request;

    /**
     * 用户登录实现
     */
    @Override
    public MemberLoginVO login(MemberLoginDTO memberLoginDTO) {
        // 初始化会员对象
        Member member = null;

        // 账号密码登录
        if (memberLoginDTO.getMobile() != null) {
            // 创建查询条件
            LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
            // 根据手机号查询用户
            wrapper.eq(Member::getMobile, memberLoginDTO.getMobile());
            // 获取用户信息
            member = this.getOne(wrapper);

            // 检查用户是否存在
            if (member == null) {
                log.info("账号不存在");
                throw new BusinessException(Resp.INVALID_USERNAME);
            }

            // 验证密码是否正确
            log.info("密码：{}", passwordEncoder.encode(memberLoginDTO.getPassword()));
            if (!passwordEncoder.matches(memberLoginDTO.getPassword(), member.getPassword())) {
                log.info("密码错误");
                throw new BusinessException(Resp.INVALID_PASSWORD);
            }
        } else {
            // 微信小程序登录流程
            String openId = null;
            // 获取openId
            WxMaJscode2SessionResult session = null;
            try {
                // 调用微信API获取session信息
                session = wxMaService.getUserService().getSessionInfo(memberLoginDTO.getCode());
                // 从session中提取openId
                openId = session.getOpenid();
                // 验证openId是否成功获取
                if (openId == null) {
                    log.info("获取openId失败");
                    throw new BusinessException(Resp.OPENID_MISSING);
                }
            } catch (WxErrorException e) {
                // 捕获微信API调用异常
                throw new BusinessException(Resp.OPENID_MISSING);
            }

            // 创建查询条件
            LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
            // 根据openId查询用户
            wrapper.eq(Member::getOpenId, openId);
            // 获取用户信息
            member = this.getOne(wrapper);

            // 检查用户是否存在
            if (member == null) {
                // 创建新用户
                member = new Member();
                // 设置openId
                member.setOpenId(openId);
                // 保存用户信息
                this.save(member);
            }
        }

        Claims claims = Jwts.claims();
        claims.put("memberId", member.getId());

        return new MemberLoginVO(
                jwtUtil.generateAccessToken(claims),
                jwtUtil.generateRefreshToken(claims)
        );
    }


    /**
     * 更新用户密码
     */
    @Override
    public void updatePassword(MemberUpdatePasswordDTO memberUpdatePasswordDTO) {

        Long id = BaseContextHandler.get();
        // 创建Member对象
        Member member = this.getById(id);

        if (member == null) {
            throw new BusinessException(Resp.MEMBER_NOT_EXIST);
        }

        // 验证新密码
        if (!passwordEncoder.matches(memberUpdatePasswordDTO.getOldPassword(), member.getPassword())) {
            log.info("旧密码错误");
            throw new BusinessException(Resp.INVALID_PASSWORD);
        }
        // 设置新密码
        member.setPassword(passwordEncoder.encode(memberUpdatePasswordDTO.getNewPassword()));
        // 更新用户信息
        this.updateById(member);
    }

    @Override
    public Member register(MemberRegisterDTO memberRegisterDTO) {
        //验证码是否正确
        if (!StringUtils.hasText(memberRegisterDTO.getCode())) {
            throw new BusinessException(Resp.CAPTCHA_MISSING);
        }

        if (!redisTemplate.hasKey("code")) {
            throw new BusinessException(Resp.CAPTCHA_EXPIRED);
        }

        String code = redisTemplate.opsForValue().get("code");

        if (code == null) {
            throw new BusinessException(Resp.CAPTCHA_EXPIRED);
        }

        if (!code.equals(memberRegisterDTO.getCode())) {
            throw new BusinessException(Resp.CAPTCHA_ERROR);
        }
        //检查手机号是否已注册&检查邮箱是否已注册
        //
        LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.hasText(memberRegisterDTO.getMobile()), Member::getMobile, memberRegisterDTO.getMobile());
        Member member = this.getOne(wrapper);

        if (member != null) {
            throw new BusinessException(Resp.MOBILE_IS_REGISTERED);
        }

        //检查密码是否合法
        if (!StringUtils.hasText(memberRegisterDTO.getPassword())) {
            throw new BusinessException(Resp.INVALID_PASSWORD);
        }
        //存储进数据库
        //解决member是null，直接调用方法会抛空指针异常的问题
        member = new Member();
        member.setMobile(memberRegisterDTO.getMobile());
        //密码需要从明文加密成密文然后再入库
        member.setPassword(passwordEncoder.encode(memberRegisterDTO.getPassword()));
        this.save(member);
        //删除验证码
        redisTemplate.delete("code");
        log.info("member:{}", member);
        return member;
    }

    /**
     * 启用或禁用会员
     * 根据会员当前状态进行切换：启用 -> 禁用，禁用 -> 启用
     *
     * @param id 会员ID
     */
    @Override
    public void enable(Long id) {
        // 1. 根据ID获取会员当前信息
        Member member = this.getById(id);
        if (member == null) {
            throw new BusinessException(Resp.MEMBER_NOT_EXIST);
        }

        // 2. 切换会员状态
        member.setStatus(member.getStatus() * -1);

        // 3. 更新会员信息
        this.updateById(member);
    }

    @Override
    public void resetPassword(Long id) {

    }

    @Override
    public Long getMemberIdByToken() {
        String accessToken = request.getHeader("Authorization");
        Claims claims = jwtUtil.parseAccessToken(accessToken);
        return claims.get("memberId", Long.class);
    }
}

